package com.config;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
public class SystemGlobals implements VariableValue {
	private static SystemGlobals globals;

	private String defaultConfig;

	private String installationConfig;

	private static Properties defaults;

	private Properties installation;

	private static List additionalDefaultsList = new ArrayList();

	private static Properties queries = new Properties();

	private static Properties transientValues = new Properties();

	private VariableExpander expander;

	private SystemGlobals() {
	}

	public static void initGlobals(String appPath, String defaults,
			String installKey) throws IOException {

		globals = new SystemGlobals();
		globals.buildSystem(appPath, defaults, installKey);
	}

	@SuppressWarnings("static-access")
	private void buildSystem(String appPath, String defaultConfig,
			String installKey) throws IOException {
		if (defaultConfig == null) {
			throw new InvalidParameterException(
					"defaultConfig could not be null");
		}
		if (installKey == null) {
			installKey = System.getProperty("user.name");
		}
		this.defaultConfig = defaultConfig;
		this.defaults = new Properties();

		this.expander = new VariableExpander(this, "${", "}");

		this.defaults.put(ConfigKeys.APPLICATION_PATH, appPath);
		this.defaults.put(ConfigKeys.INSTALLATION, installKey);
		this.defaults.put(ConfigKeys.DEFAULT_CONFIG, defaultConfig);

		loadDefaults();

	}

	public static void setValue(String field, String value) {
		globals.installation.put(field, value);
		globals.expander.clearCache();
	}

	public static void setTransientValue(String field, String value) {
		transientValues.put(field, value);
	}

	@SuppressWarnings("static-access")
	public static void loadDefaults() throws IOException {

		FileInputStream input = new FileInputStream(globals.defaultConfig);
		globals.defaults.load(input);
		input.close();
		globals.expander.clearCache();

	}

	@SuppressWarnings("unchecked")
	public static void loadAdditionalDefaults(String file) throws IOException {
		FileInputStream input = new FileInputStream(file);
		globals.installation.load(input);
		input.close();
		if (!additionalDefaultsList.contains(file)) {
			additionalDefaultsList.add(file);
		}
	}

	public static void saveInstallation() throws IOException {

		Properties p = new Properties();
		p.putAll(globals.installation);
		FileOutputStream out = new FileOutputStream(globals.installationConfig);
		p.store(out, "Installation specific configuration options");
		out.close();
	}

	public static String getValue(String field) {
		return globals.getVariableValue(field);
	}

	public static String getTransientValue(String field) {
		return transientValues.getProperty(field);
	}

	public static int getIntValue(String field) {
		return Integer.parseInt(getValue(field));
	}

	public static boolean getBoolValue(String field) {
		return "true".equals(getValue(field));
	}

	@SuppressWarnings("static-access")
	public String getVariableValue(String field) {
		String preExpansion = this.defaults.getProperty(field);
		if (preExpansion == null) {
			return null;
		}
		return expander.expandVariables(preExpansion);
	}

	public static void loadQueries(String queryFile) throws IOException {
		queries.load(new FileInputStream(queryFile));
	}

	public static String getSql(String sql) {
		return queries.getProperty(sql);
	}

	@SuppressWarnings("static-access")
	public static Iterator fetchConfigKeyIterator() {
		return globals.defaults.keySet().iterator();
	}
}